package com.gwtjs.icustom.controller.install;

import java.io.IOException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gwtjs.icustom.entity.ResultWrapper;
import com.gwtjs.icustom.entity.SSHClientVO;
import com.gwtjs.icustom.mapper.ServerHostMapper;
import com.gwtjs.icustom.pojo.ServerHost;
import com.gwtjs.icustom.utils.JScpUtil;
import com.gwtjs.icustom.utils.LinuxIPUtil;
import com.gwtjs.icustom.utils.ShellUtil;

/**
 * <h2>设置系统XXX</h2>
 * 
 * @author flash aGuang flash8627@hotmail.com 8538191@qq.com 2023/07/14
 *
 */
@RestController
@RequestMapping("/set/system")
public class SetSystemController {

	private final static Logger logger = LoggerFactory.getLogger(SetSystemController.class);

	@Value("${app.work.home}")
	private String workHome;

	@Autowired
	private ServerHostMapper serverHostMapper;
	
	@PutMapping("/autoStart")
	public ResultWrapper autoOptimizeStart() throws Exception {
		logger.info("\n开始自动优化...............\n");
		List<ServerHost> records=serverHostMapper.queryHostList();
		
		ResultWrapper result = this.setFirewall(records);
		result = this.setSelinux(records);

		result = this.setSsh(records);
		result = this.setHosts(records);
		result = this.optimization(records);
		
		for (ServerHost host : records) {
			host.setFirewallFlag(1);
			host.setSelinuxFlag(1);
			host.setSshFlag(1);
			host.setIsHostsFlag(1);
			host.setIsOptimize(1);
			serverHostMapper.updateSetStatus(host);
		}logger.info("\n完成自动优化...............\n{}",result);
		
		return ResultWrapper.constructSuccessResult(records);
	}
	/**
	 * <h2>设置系统-防火墙</h2>
	 * 
	 * @author flash aGuang flash8627@hotmail.com 8538191@qq.com
	 *         http://192.168.152.101:8080/host/update/firewall
	 *         <code>[{"id":1,"hostIp":"192.168.152.100","hostName":"hdp123","hostPort":"22","account":"root","password":"rootroot123"},
	    {"id":2,"hostIp":"192.168.152.101","hostName":"hdp3","hostPort":"22","account":"root","password":"rootroot123"}]</code>
	 *         2023/07/14
	 */
	@PutMapping("/firewall")
	public ResultWrapper setFirewall(@RequestBody List<ServerHost> records) {
		String cmd = "ip addr";
		ShellUtil execute = null;
		String result = null;
		for (ServerHost host : records) {
			cmd = "systemctl stop firewalld && systemctl disable firewalld && sestatus  && systemctl status firewalld";
			execute = new ShellUtil(host.getHostIp(), host.getAccount(), host.getPassword(), host.getHostPort());
			// 执行命令
			result = execute.executeForResult(cmd);
			logger.info("\n/firewall:{}\nresult:{}\n",cmd,result);
			execute.close();

		}
		return ResultWrapper.successResult(records);

	}

	/**
	 * <h2>设置系统-selinux</h2>
	 * 
	 * @author flash aGuang flash8627@hotmail.com 8538191@qq.com 2023/07/14
	 *
	 */
	@PutMapping("/selinux")
	public ResultWrapper setSelinux(@RequestBody List<ServerHost> records) {
		String cmd = "ip addr";
		ShellUtil execute = null;
		String result = null;
		for (ServerHost host : records) {
			execute = new ShellUtil(host.getHostIp(), host.getAccount(), host.getPassword(), host.getHostPort());
			
			cmd = "sed -ri '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config";
			result = execute.executeForResult(cmd);
			logger.info("\n/selinux:{}\nresult:{}\n",cmd,result);
			
			cmd = "sed -ri '/^SELINUX=/c SELINUX=disabled' /etc/sysconfig/selinux";
			result = execute.executeForResult(cmd);
			logger.info("\n/selinux:{}\nresult:{}\n",cmd,result);
			
			execute.close();

		}
		return ResultWrapper.successResult(records);

	}

	/**
	 * <h2>设置系统hosts</h2>
	 * 
	 * @author flash aGuang flash8627@hotmail.com 8538191@qq.com 2023/07/14
	 * @throws Exception 
	 *
	 */
	@PutMapping("/hosts")
	public ResultWrapper setHosts(@RequestBody List<ServerHost> records) throws Exception {
		logger.info("records size:{}\nis null:{}\n",records.size()+"",(records==null));
		if(records.isEmpty()) {
			return ResultWrapper.successResult("主机列表空");
		}
		
		// 所有主机执行的指令相同
		String cmd = "";
		final String fileName = "hosts.sh";
		final String templateName = String.format("%s-template", fileName);
		final String local = String.format("%s/shell/%s", workHome,templateName);
		
		String localIp = LinuxIPUtil.getLinuxLocalIp();
		logger.info("\n hosts linux local IP:{}\n",localIp);
		ServerHost server = serverHostMapper.queryHostByIp(localIp);
		ShellUtil execute = new ShellUtil(server);
		String result = null;
		ServerHost record=records.get(0);
		
		//覆盖拷贝
		cmd = String.format("\\cp -rf %s/shell/%s-src %s", workHome,fileName,local);
		logger.info("\n script copy cmd:{}\n",cmd);
		result = execute.executeForResult(cmd);
		
		//替换验证的IP
		cmd = String.format("sed -i 's/template_ip/%s/g' %s", record.getHostIp(),local);
		logger.info("\n hosts cmd:{}\n",cmd);
		result = execute.executeForResult(cmd);
		
		//替换验证的主机名
		cmd = String.format("sed -i 's/template_hostname/%s/g' %s", record.getHostName(),local);
		logger.info("\n hosts cmd:{}\n",cmd);
		result = execute.executeForResult(cmd);
		
		//添加IP 主机名映射
		result = exeHostsScript(records,local,server);
		logger.info("\n 脚本已经替换请验证 result:{}\n",result);
		
		for (ServerHost host : records) {
			JScpUtil.upload(host, local, "/tmp");
			
			execute = new ShellUtil(host);
			cmd = String.format("\\cp -rf /tmp/%s /opt/%s", templateName,fileName);
			logger.info("\n hosts cmd:{}\n",cmd);
			// 执行命令
			result = execute.executeForResult(cmd);
			
			cmd = String.format("chmod o+x /opt/%s && /opt/%s", fileName, fileName);
			logger.info("\n 执行脚本文件:{}\n",cmd);
			result = execute.executeForResult(cmd);

			logger.info("\n hosts result:{}\n",result);
			execute.close();

		}
		return ResultWrapper.successResult();

	}

	/**
	 * <h1>%s.pub文件聚集到本机</h1>
	 * <ul><ol>
	 * <li><h2>id_rsa.pub更名 为主机名.pub，聚集所有id_rsa.pub到入口主机,</h2></li>
	 * <li><h2>主机名.pub文件cat到authorized_keys文件，将authorized_keys文件发送到集群所有主机，实现双向免密</h2></li>
	 * </ol></ul>
	 * <p>  这里有个小插曲，直接将 *.pub发送到/root/.ssh/目录会SCPRemoteException: Remote SCP command had error: scp: /root/.ssh/hdp2.pub: Broken pipe异常</p>
	 * 
	 * @param records
	 * @return
	 * @throws Exception
	 */
	@PutMapping("/gather")
	public ResultWrapper gatherSSHConfig(@RequestBody List<ServerHost> records) throws Exception {
		
		String local = "/tmp/";
		ShellUtil execute = null;
		String result = null;

		ServerHost server = null;
		for (ServerHost host : records) {
			String remote = String.format("/root/.ssh/%s.pub", host.getHostName());
			
			SSHClientVO po = JScpUtil.download(host, local, remote);
			String localAddress = po.getLocalAddress();
			String remoteAddress = po.getRemoteAddress();
			logger.info("local Address={} ,remote Address={} ", localAddress, remoteAddress);
			if(localAddress.equals(host.getHostIp())) {
				server = this.getServer(host);
			}
		}
		
		logger.info("\nlocal ssh --> server:{} \n", server);
		
		//生成authorized_keys文件
		String cmd = "ls /tmp/*.pub";
		logger.info("cmd:{} ", cmd);
		execute = new ShellUtil(server.getHostIp(), server.getAccount(), server.getPassword(), server.getHostPort());		
		result = execute.executeForResult(cmd);
		logger.info("\nssh search tmp/*.pub result:{} \n", result);
				
		//生成authorized_keys文件
		cmd = "cd ~/.ssh/ && rm -rf authorized_keys && cat /tmp/*.pub >> authorized_keys";
		logger.info("cmd:{} ", cmd);
		execute.executeForResult(cmd);
		
		//将authorized_keys分发到集群各主机
		for (ServerHost host : records) {
			local = "/root/.ssh/authorized_keys";
			final String remote = "/root/.ssh/";
			
			JScpUtil.upload(host, local, remote);
		}
		
		return ResultWrapper.successResult();
	}
	
	/**
	 * <取入口主机>
	 * @param host
	 * @return
	 */
	private ServerHost getServer(ServerHost host) {
		ServerHost server = null;
		if(host==null) {
			return null;
		}
		if (host.getHostIp() != null || !"".equals(host.getHostIp())) {
			server = new ServerHost();
			server.setHostIp(host.getHostIp());
			server.setHostName(host.getHostName());
			server.setHostPort(host.getHostPort());
			server.setAccount(host.getAccount());
			server.setPassword(host.getPassword());
		}
		return server;
	}

	/**
	 * <h2>设置系统-SSH免密</h2>
	 * 
	 * @author flash aGuang flash8627@hotmail.com 8538191@qq.com 2023/07/14
	 * @throws Exception 
	 *
	 */
	@PutMapping("/ssh")
	public ResultWrapper setSsh(@RequestBody List<ServerHost> records) throws Exception {

		String cmd = "ip addr";
		ShellUtil execute = null;

		String result = null;

		for (ServerHost host : records) {
			// 生成ssh key 并且重命名
			cmd = "rm -rf ~/.ssh/* ";
			logger.info("\ncmd:{}\n ", cmd);
			execute = new ShellUtil(host.getHostIp(), host.getAccount(), host.getPassword(), host.getHostPort());
			// 执行命令
			result = execute.executeForResult(cmd);

			// 执行命令
			cmd = "ssh-keygen -t dsa -f ~/.ssh/id_dsa -P '' && cd ~/.ssh/ && mv id_dsa.pub %s.pub ";
			cmd = String.format(cmd, host.getHostName());
			logger.info("\ncmd:{} \n", cmd);
			
			result = execute.executeForResult(cmd);
			execute.close();
			logger.info("\n执行ssh-keygen \n{}\n", result);

		}

		this.gatherSSHConfig(records);

		return ResultWrapper.successResult(records);

	}
	
	/**
	 * <h2>设置系统-系统优化</h2>
	 * <p>
	 *  <h3>优化以下两个文件</h3>
	 * <ul>
	 * <ol><li>/etc/rc.d/rc.local</li><li>/etc/security/limits.conf</li></ol>
	 * </ul>
	 * <code>
	 * </code>
	 * </p>
	 * 
	 * @author flash aGuang flash8627@hotmail.com 8538191@qq.com 2023/07/14
	 * @throws IOException 
	 *
	 */
	@PutMapping("/optimization")
	public ResultWrapper optimization(@RequestBody List<ServerHost> records) throws IOException {
		String cmd = "ip addr";
		String local = String.format("%s/shell/",workHome);
		logger.info("\nlocal path  {}\n", local);
		String remote = "/tmp";
		ShellUtil execute = null;

		//String result = null;
		String[] localfs = {"limits.conf.sh","rc.local.sh","sysctl.conf.sh","20-nproc.conf.sh","rpcbind.sh"};
		for (ServerHost host : records) {
			for (String sh : localfs) {
				JScpUtil.upload(host, local+sh, remote);
				
				execute = new ShellUtil(host.getHostIp(), host.getAccount(), host.getPassword(), host.getHostPort());
				cmd = String.format("chmod 755 /tmp/%s && /tmp/%s", sh,sh);
				execute.executeForResult(cmd);
				
				cmd = String.format("rm -rf /tmp/%s", sh);
				execute.executeForResult(cmd);
				
				execute.close();
			}

		}
		return ResultWrapper.successResult(records);

	}
	
	/**
	 * <h2>获取/etc/hosts配置字符</h2> <cod>得到如下结果：echo '192.168.23.21 hdp1.ambari' >>
	 * /etc/hosts \n </cod>
	 * @param file 脚本文件路径加文件名
	 * @param records 主机列表信息
	 * @return
	 */
	private String exeHostsScript(List<ServerHost> records,String file,ServerHost server) {
		logger.info("\nhosts txt size: " + records.size());
		ShellUtil execute = new ShellUtil(server.getHostIp(), server.getAccount(), server.getPassword(), server.getHostPort());
		String cmd = "";
		String result = "";
		for (ServerHost host : records) {
			cmd = String.format("sed -i '8i%s %s' %s",host.getHostIp(),host.getHostName(), file);
			logger.info("\n sed hosts cmd:{}\n",cmd);
			result = execute.executeForResult(cmd);
		}
		
		cmd = String.format("cat %s", file);
		logger.info("\n format hosts script cmd:{}\n",cmd);
		result = execute.executeForResult(cmd);
		execute.close();
		
		return result;
	}

}
